/**
 * 如果某个数组之和是K的倍数，称之为漂亮的
 * 现在给定一个数组，将其划分成若干个子数组，问能得到的漂亮的子数组最多是多少
 * 
 * 预处理模K的前缀和，记作Si
 * 再预处理与Si相等的前一个为止，记作Pre[i]
 * 设Di是到i为止能够划分出的最大数量，Ti是i以内的最大值
 * 则 Di = max(D[Pre[i]] + 1, T[i - 1])
 * Ti = max(Di, T[i - 1])
 * 
 * 标程说可以贪心
 */
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;

using llt = long long;
using vi = vector<int>;
using pii = pair<int, int>;

int N, K;
vi A;
vector<int> S;
vector<int> D;
vector<int> T;
vector<int> Pre;

int proc(){
    map<int, vi> pos;
    pos[0].push_back(0);

    S.assign(N + 1, 0);
    for(int i=1;i<=N;++i){
        pos[S[i] = (S[i - 1] + A[i]) % K].push_back(i);
    }

    Pre.assign(N + 1, -1);
    for(const auto & p : pos){
        const auto & v = p.second;
        for(int i=1,n=v.size();i<n;++i){
            Pre[v[i]] = v[i - 1];
        }     
    }

    D.assign(N + 1, 0);
    T.assign(N + 1, 0);
    for(int i=1;i<=N;++i){
        D[i] = T[i - 1];
        if(-1 != Pre[i]) D[i] = max(D[Pre[i]] + 1, D[i]);
        T[i] = max(D[i], T[i - 1]);
    }

    return D[N];
}

void work(){
    cin >> N >> K;
    A.assign(N + 1, {});
    for(int i=1;i<=N;++i) cin >> A[i];
    cout << proc() << "\n";
    return;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int nofkase = 1;
    // cin >> nofkase;
    while(nofkase--) work();
    return 0;
}